Option Explicit

' ======================================================================
' Descriptor
' SQL 格式化器使用的: 对齐元素分组的对齐器
' ======================================================================

' ======================================================================
' Field
' ======================================================================
' ==================================================
' 初始化时需要加载的内容
' ==================================================
Private config As SqlFormatterConfiguration

' ==================================================
' 执行对齐时使用的缓存
' ==================================================
' 校正对齐元素的长度缓存--rectifyAlignmentSize
Private alignmentSizeSet As ISet
' 每个级别下的每个对齐元素内的右侧元素分组栈
' ObjStack<IObjArrayRef<IObjArrayRef<ISqlFormatterAlignmentElem>>>
Private rightGroupsStack As ObjStack

' ======================================================================
' 初始化方法
' ======================================================================
Private Sub Class_Initialize()
    ' 校正对齐元素的长度--rectifyAlignmentSize
    Set alignmentSizeSet = UtilsSet.createHashSet

    ' 每个级别下的每个对齐元素内的右侧元素分组栈
    Set rightGroupsStack = New ObjStack
End Sub

Private Sub Class_Terminate()
    Set alignmentSizeSet = Nothing
    Set rightGroupsStack = Nothing
    Set config = Nothing
End Sub

' ======================================================================
' Init
' ======================================================================
' 初始化 SqlFormatterAligner
'
' @param configVal 格式化配置对象
Public Sub Init(ByRef configVal As SqlFormatterConfiguration)
    Set config = configVal
End Sub

' ======================================================================
' 对齐单一分组
' ======================================================================
' 对齐单一分组--对齐元素分组做内部对齐
'
' @param group 对齐元素分组 (IObjArrayRef<ISqlFormatterAlignmentElem>)
Public Sub alignmentOneElemGroup(ByRef group As IObjArrayRef)
    ' 1. 计算这个组的最大对齐长度 `maxLen`
    Dim maxLen As Integer
    maxLen = getGroupMaxAlignmentSize(group)
    ' 2. 检查: 如果 `maxLen != -1`，则对这一分组作对齐: `doAlignmentElemGroup(maxLen, group)`
    If maxLen <> -1 Then
        doAlignmentElemGroup maxLen, group
    End If
End Sub

' ======================================================================
' 对齐多个元素分组
' ======================================================================
' 对齐元素分组
'
' @param groups 对齐元素分组集合 (IObjArrayRef<IObjArrayRef<ISqlFormatterAlignmentElem>>)
Public Sub alignmentElem(ByRef groups As IObjArrayRef)
    ' 兼顾所有级别的对齐元素分组做对齐
    If config.alignmentLevel = SqlAlignmentLevel.ALL_LEVEL Then
        alignmentElemGroupsAllLevel groups

    ' 只在每个对齐元素分组内做对齐
    ElseIf config.alignmentLevel = SqlAlignmentLevel.INTERNAL Then
        alignmentElemGroupsInternal groups
    End If
End Sub

' 只在每个对齐元素分组内做对齐
'
' @param groups 对齐元素分组 (IObjArrayRef<IObjArrayRef<ISqlFormatterAlignmentElem>>)
Private Sub alignmentElemGroupsInternal(ByRef groups As IObjArrayRef)
    ' ==================================================
    ' 1. 检查参数
    ' ==================================================
    ' 1. 检查: 如果对齐元素分组是空 `groups == null`，则退出处理
    If groups Is Nothing Then
        Exit Sub
    End If

    ' ==================================================
    ' 2. 声明变量
    ' ==================================================
    ' 1. 遍历索引 `long i`
    Dim i As Long
    ' 2. 对齐元素分组 `IObjArrayRef<ISqlFormatterAlignmentElem> group`
    Dim group As IObjArrayRef
    ' 3. 最大对齐长度 `int maxLen`
    Dim maxLen As Integer
    ' 4. 临时对齐元素分组集合 `IObjArrayRef<IObjArrayRef<ISqlFormatterAlignmentElem>> tempGroups`
    Dim tempGroups As IObjArrayRef
    ' 5. 遍历索引 `long j`
    Dim j As Long
    ' 6. 对齐元素 `ISqlFormatterAlignmentElem elem`
    Dim elem As ISqlFormatterAlignmentElem

    ' ==================================================
    ' 3. 遍历每个分组
    ' ==================================================
    ' 1. 从 `i = 0` 开始到 `groups.MaxIndex` 遍历 `groups`
    For i = 0 To groups.MaxIndex
        ' 2. 获取第 i 个分组，保存到 `group`
        Set group = groups.Item(i)
        ' 3. 计算这个组的最大对齐长度 `maxLen`
        maxLen = getGroupMaxAlignmentSize(group)
        ' 4. 检查: 如果 `maxLen != -1`，则对这一分组作对齐: `doAlignmentElemGroup(maxLen, group)`
        If maxLen <> -1 Then
            doAlignmentElemGroup maxLen, group
        End If

        ' 5. 处理这个分组内部存在的子分组
        ' 5.1. 从 j = 0 开始到 `group.MaxIndex` 遍历 `group`
        For j = 0 To group.MaxIndex
            ' 5.2. 获取第 j 个对齐元素，保存到 `elem`
            Set elem = group.Item(j)

            ' 5.3. 处理对齐元素的左侧元素中可能存在的子分组
            ' 5.3.1. 从这个对齐元素中获取左侧元素中包含的子分组，保存到 `tempGroups`: `getAlignmentElemGroupsFromLeftElem`
            Set tempGroups = elem.getAlignmentElemGroupsFromLeftElem
            ' 5.3.2. 对 `tempGroups` 执行: 只在每个对齐元素分组内做对齐---INTERNAL
            alignmentElemGroupsInternal tempGroups

            ' 5.4. 处理对齐元素的右侧元素中可能存在的子分组
            ' 5.4.1. 从这个对齐元素中获取右侧元素中包含的子分组，保存到 `tempGroups`: `getAlignmentElemGroupsFromRightElem`
            Set tempGroups = elem.getAlignmentElemGroupsFromRightElem
            ' 5.4.2. 对 `tempGroups` 执行: 只在每个对齐元素分组内做对齐---INTERNAL
            alignmentElemGroupsInternal tempGroups
        Next

    Next
End Sub

' 兼顾所有级别的对齐元素分组做对齐的驱动
'
' @param groups 对齐元素分组集合 (IObjArrayRef<IObjArrayRef<ISqlFormatterAlignmentElem>>)
Private Sub alignmentElemGroupsAllLevel(ByRef groups As IObjArrayRef)
    ' ==================================================
    ' 1. 兼顾所有级别的对齐元素分组做对齐--只对每个元素及这个元素的左侧元素执行对齐
    ' ==================================================
    alignmentElemGroupsAllLevelForMiddleAndLeft groups

    ' ==================================================
    ' 2. 处理每一级别的右侧分组
    ' ==================================================
    ' 1. 检查: 如果缓存栈 `rightGroupsStack.Count > 0`，则继续
    If rightGroupsStack.Count > 0 Then
        ' 2. 声明变量
        ' 2.1. 右侧分组 `IObjArrayRef<IObjArrayRef<ISqlFormatterAlignmentElem>> rightGroups`
        Dim rightGroups As IObjArrayRef

        ' 3. 遍历 `rightGroupsStack`，直到 `rightGroupsStack.Count <= 0`
        While rightGroupsStack.Count > 0
            ' 4. 从栈中弹出一个分组，保存到 `rightGroups`
            Set rightGroups = rightGroupsStack.pop

            ' 5. 对 `rightGroups` 做： 兼顾所有级别的对齐元素分组做对齐--只对每个元素及这个元素的左侧元素执行对齐
            '    这里仍然会递归，并吸收更多的右侧分组到缓存栈中，所以只要继续循环即可
            alignmentElemGroupsAllLevelForMiddleAndLeft rightGroups
        Wend
    End If
End Sub

' 兼顾所有级别的对齐元素分组做对齐--只对每个元素及这个元素的左侧元素执行对齐
'
' @param groups 对齐元素分组集合 (IObjArrayRef<IObjArrayRef<ISqlFormatterAlignmentElem>>)
Private Sub alignmentElemGroupsAllLevelForMiddleAndLeft(ByRef groups As IObjArrayRef)
    ' ==================================================
    ' 1. 检查参数
    ' ==================================================
    ' 1. 检查: 如果对齐元素分组集合是空 `groups == null`，则退出处理
    If groups Is Nothing Then
        ' return
        Exit Sub
    End If

    ' ==================================================
    ' 2. 初始化参数
    ' ==================================================
    ' 1. 每一个分组 `IObjArrayRef<ISqlFormatterAlignmentElem> group`
    Dim group As IObjArrayRef
    ' 2. 分组下的对齐元素 `ISqlFormatterAlignmentElem elem`
    Dim elem As ISqlFormatterAlignmentElem
    ' 3. 遍历索引 `long i`
    Dim i As Long
    ' 4. 遍历索引 `long j`
    Dim j As Long
    ' 5. 左侧元素中的分组集合 `IObjArrayRef<IObjArrayRef<ISqlFormatterAlignmentElem>> leftGroups`
    Dim leftGroups As IObjArrayRef
    ' 6. 右侧元素中的分组集合 `IObjArrayRef<IObjArrayRef<ISqlFormatterAlignmentElem>> rightGroups`
    Dim rightGroups As IObjArrayRef
    ' 7. 临时分组集合 `IObjArrayRef<IObjArrayRef<ISqlFormatterAlignmentElem>> tempGroup`
    Dim tempGroup As IObjArrayRef

    ' ==================================================
    ' 3. 获取每个对齐元素的左侧元素和右侧元素中包含的子分组
    ' ==================================================
    ' 4.1. 遍历 `groups` 中的每一个 `group`
    For i = 0 To groups.MaxIndex
        Set group = groups.Item(i)

        ' 4.2. 遍历 `group` 中的每一个元素 `elem`
        For j = 0 To group.MaxIndex
            Set elem = group.Item(j)

            ' ==============================
            ' 4.3. 处理左侧元素中的子分组
            ' ==============================
            ' 1. 从这个对齐元素中的左侧元素中获取子分组，保存到 `tempGroup`
            Set tempGroup = elem.getAlignmentElemGroupsFromLeftElem
            ' 2. 检查: 如果存在子分组: `tempGroup != null`，则继续
            If Not tempGroup Is Nothing Then
                ' 3. 检查: 如果分组集合还没有创建 `leftGroups == null`，则创建 `UtilsArrayRef.createRealObjArrayRef<ISqlFormatterAlignmentElem>(8)`
                If leftGroups Is Nothing Then
                    Set leftGroups = UtilsArrayRef.createRealObjArrayRef(8)
                End If
                ' 4. 将 `tempGroup` 保存到 `leftGroups`
                leftGroups.mergeArrRef tempGroup
            End If

            ' ==============================
            ' 4.4. 处理右侧元素中的子分组
            ' ==============================
            ' 1. 从这个对齐元素中的右侧元素中获取子分组，保存到 `tempGroup`
            Set tempGroup = elem.getAlignmentElemGroupsFromRightElem
            ' 2. 检查: 如果存在子分组: `tempGroup != null`，则继续
            If Not tempGroup Is Nothing Then
                ' 3. 检查: 如果分组集合还没有创建 `rightGroups == null`，则创建 `UtilsArrayRef.createRealObjArrayRef<ISqlFormatterAlignmentElem>(8)`
                If rightGroups Is Nothing Then
                    Set rightGroups = UtilsArrayRef.createRealObjArrayRef(8)
                End If
                ' 4. 将 `tempGroup` 保存到 `rightGroups`
                rightGroups.mergeArrRef tempGroup
            End If
        Next
    Next

    ' ==================================================
    ' 4. 对齐左侧元素中包含的子分组集合
    ' ==================================================
    ' 1. 检查: 如果左侧存在子分组集合 `leftGroups != null`，则继续
    If Not leftGroups Is Nothing Then
        ' 2. 调用当前驱动，执行 `leftGroups` 的对齐
        alignmentElemGroupsAllLevel leftGroups
    End If

    ' ==================================================
    ' 5. 对当前的 `groups` 进行对齐
    ' ==================================================
    doAlignmentElemGroupsAllLevel groups

    ' ==================================================
    ' 6. 对齐右侧元素中包含的子分组集合
    ' ==================================================
    ' 1. 检查: 如果右侧存在子分组集合 `rightGroups != null`，则继续
    If Not rightGroups Is Nothing Then
        ' 2. 将 `rightGroups` 暂存到右侧对齐元素分组的栈中: `rightGroupsStack`
        rightGroupsStack.push rightGroups
    End If
End Sub

' 兼顾所有级别的对齐元素分组做对齐
'
' @param groups 对齐元素分组集合 (IObjArrayRef<IObjArrayRef<ISqlFormatterAlignmentElem>>)
Private Sub doAlignmentElemGroupsAllLevel(ByRef groups As IObjArrayRef)
    ' ==================================================
    ' 1. 声明变量
    ' ==================================================
    ' 1. 分组集合的最大索引 `long groupsMaxIndex`
    Dim groupsMaxIndex As Long
    ' 2. 遍历索引 `long i`
    Dim i As Long
    ' 3. 遍历索引 `long j`
    Dim j As Long
    ' 4. 批量分组对齐时使用的索引 `long x`
    Dim x As Long
    ' 5. 分组索引 `long groupIndex`
    Dim groupIndex As Long
    ' 6. 每个分组的缓存数据 `PrimitivePair pair`
    Dim pair As PrimitivePair
    ' 7. 最大长度 `int maxLen`
    Dim maxLen As Integer
    ' 8. 临时长度 `int tempLen`
    Dim tempLen As Integer
    ' 9. 校正后的最大长度 `int rectifyMaxLen`
    Dim rectifyMaxLen As Integer
    ' 10. 每个分组的最大长度数据的缓存 `IObjArrayRef<PrimitivePair> groupMaxSizeCache`
    Dim groupMaxSizeCache As IObjArrayRef
    ' 11. 对齐元素分组 `IObjArrayRef<ISqlFormatterAlignmentElem> g`
    Dim g As IObjArrayRef

    ' ==================================================
    ' 2. 初始化变量
    ' ==================================================
    ' 1. 保存分组结合的最大索引到 `groupsMaxIndex`
    groupsMaxIndex = groups.MaxIndex

    ' ==================================================
    ' 3. 检查: 如果 `groups` 的数量，如果只有 1 个分组
    ' ==================================================
    If groupsMaxIndex = 0 Then
        Set g = groups.Item(0)

        ' 1. 计算这个组的最大对齐长度 `maxLen`: `getGroupMaxAlignmentSize`
        maxLen = getGroupMaxAlignmentSize(g)

        ' 2. 检查: 如果 `maxLen == -1`，则退出处理
        '    这里表示这个分组不需要做对齐
        If maxLen = -1 Then
            ' return
            Exit Sub
        End If

        ' 3. 校正最大长度，结果保存到 `rectifyMaxLen`
        rectifyMaxLen = rectifyAlignmentSize(maxLen)

        ' 4. 检查: 如果校正成功 `rectifyMaxLen != -1` ，则设置 `maxLen = rectifyMaxLen`
        If rectifyMaxLen <> -1 Then
            maxLen = rectifyMaxLen

        ' 5. 否则，缓存这个最大长度，并直接使用计算出来的最大长度 `maxLen`
        Else
            cacheAlignmentSize maxLen
        End If

        ' 6. 对这一分组作对齐
        doAlignmentElemGroup maxLen, g

        ' 7. 退出处理
        ' return
        Exit Sub
    End If

    ' ==================================================
    ' 4. 否则，计算每个分组中的最长字符串长度，并排序
    ' ==================================================
    ' 1. 创建一个数组引用来保存长度信息，保存到 `groupMaxSizeCache`
    Set groupMaxSizeCache = UtilsArrayRef.createRealObjArrayRef(groupsMaxIndex + 1)

    ' 2. 遍历 `groups`，收集各个分组的最大对齐长度
    ' 2.1 从 `i = 0` 到 `groupsMaxIndex` 遍历 `groups`
    For i = 0 To groupsMaxIndex
        Set g = groups.Item(i)

        ' 2.2. 计算当前分组的最大对齐长度，并保存到缓存对象: `tempLen = getGroupMaxAlignmentSize(groups[i])`
        tempLen = getGroupMaxAlignmentSize(g)
        ' 2.3. 检查: 如果 `tempLen == -1`，则跳过这个分组
        If tempLen = -1 Then
            GoTo getMaxSizeContinue
        End If

        ' 2.4. 创建一个长度的缓存对象，保存到 `pair`: `new PrimitivePair()`
        Set pair = New PrimitivePair
        ' 2.5. 保存当前分组的索引到缓存对象: `pair.Key1 = i`
        pair.Key1 = i
        ' 2.6. 保存当前分组的最大对齐长度: `pair.Key2 = tempLen`
        pair.Key2 = tempLen
        ' 2.7. 将这个缓存对象添加到`groupMaxSizeCache`
        groupMaxSizeCache.Add pair

getMaxSizeContinue:
    Next

    ' 3. 检查: 如果长度信息数组容量为 0 ，则退出处理: `groupMaxSizeCache.Count == 0`
    If groupMaxSizeCache.Count = 0 Then
        ' return
        Exit Sub
    End If

    ' 3. 对长度信息 `groupMaxSizeCache` 进行排序
    '    因为每个元素是 `PrimitivePair`，所以按照 `PrimitivePair.Key2` 进行排序
    UtilsSort.sortAscPrimitivePairByKey2 groupMaxSizeCache

    ' 5. 重新获取 `groupsMaxIndex = groupMaxSizeCache.MaxIndex`
    groupsMaxIndex = groupMaxSizeCache.MaxIndex

    ' ==================================================
    ' 5. 遍历缓存 `groupMaxSizeCache`，并进行对齐，直到所有的分组都被消耗完
    ' ==================================================
    ' 5.1. 从 `i = 0` 开始到 `groupsMaxIndex` 遍历 `groupMaxSizeCache`
    For i = 0 To groupsMaxIndex
        ' 5.2. 获取第 i 个分组的对齐信息到 `pair`
        Set pair = groupMaxSizeCache.Item(i)

        ' 5.3. 获取这个分组的最大长度 `maxLen = pair.Key2`
        maxLen = pair.Key2

        ' 5.4. 校正最大长度，结果保存到 `rectifyMaxLen`
        rectifyMaxLen = rectifyAlignmentSize(maxLen)

        ' ==============================
        ' 5.5. 检查: 如果校正成功 `rectifyMaxLen != -1`
        ' ==============================
        If rectifyMaxLen <> -1 Then
            ' 1. 保存分组索引 `groupIndex = pair.Key1`
            groupIndex = pair.Key1
            ' 2. 对这一分组作对齐: `doAlignmentElemGroup(rectifyMaxLen, groups[groupIndex])`
            doAlignmentElemGroup rectifyMaxLen, groups.Item(groupIndex)
            ' 3. 从 2 开始下一轮遍历
            GoTo loopContinue

        ' ==============================
        ' 5.6. 否则 (校正失败)
        ' ==============================
        Else
            ' 1. 计算兼容的最大对齐长度
            '    在这里，maxLen 已经是这个分组的最大长度了，参考: 2 `maxLen = pair.Key2`
            rectifyMaxLen = maxLen + config.multiNestAlignmentStrSizeDiff
            ' 2. 遍历，搜索一个不超过这个长度的最大长度
            ' 2.1. 从 `j = i + 1` 开始到 `groupsMaxIndex`，遍历 `groupMaxSizeCache`
            For j = i + 1 To groupsMaxIndex
                ' 2.2. 获取第 j 个分组的对齐信息到 `pair`
                Set pair = groupMaxSizeCache.Item(j)
                ' 2.3. 保存这个分组的最大长度 `tempLen`
                tempLen = pair.Key2
                ' 2.4. 检查: 如果超出了校正的范围，退出这一级遍历
                If tempLen > rectifyMaxLen Then
                    Exit For

                ' 2.5. 否则，检查: 如果 `tempLen > maxLen`，则设置 `maxLen = tempLen`
                ElseIf tempLen > maxLen Then
                    maxLen = tempLen
                End If
            Next

            ' 3. 缓存这个最大长度
            cacheAlignmentSize maxLen

            ' 4. 遍历，对范围内的各个分组进行对齐
            ' 4.1. 从 `x = i` 开始到 `j - 1` 遍历 `groups`
            For x = i To j - 1
                ' 4.2. 获取第 x 个分组的对齐信息到 `pair`
                Set pair = groupMaxSizeCache.Item(x)

                ' 4.3. 保存分组索引 `groupIndex = pair.Key1`
                groupIndex = pair.Key1

                ' 4.4. 对这一分组作对齐: `doAlignmentElemGroup(maxLen, groups[groupIndex])`
                doAlignmentElemGroup maxLen, groups.Item(groupIndex)
            Next

            ' 5. 设置 `i = j - 1`
            i = j - 1

            ' 6. 从 2 开始下一轮遍历
        End If
loopContinue:
    Next
End Sub

' 计算分组中最长的对齐字符串的长度
'
' @param groups 对齐元素分组 (IObjArrayRef<ISqlFormatterAlignmentElem>)
' @return 分组中最长的对齐字符串的长度
Private Function getGroupMaxAlignmentSize(ByRef group As IObjArrayRef) As Integer
    ' int result = -1
    ' 这里直接使用 getGroupMaxAlignmentSize
    getGroupMaxAlignmentSize = -1

    Dim i As Long
    Dim elem As ISqlFormatterAlignmentElem
    Dim temp As Integer
    For i = 0 To group.MaxIndex
        Set elem = group.Item(i)

        temp = elem.getAlignmentSize(config)

        ' 如果当前分组不需要对齐，则跳过
        If temp = -1 Then
            GoTo loopContinue
        End If

        If temp > getGroupMaxAlignmentSize Then
            getGroupMaxAlignmentSize = temp
        End If
loopContinue:
    Next

    ' return result
End Function

' 对指定对齐元素分组作对齐
'
' @param maxAlignmentSize 最大对齐长度
' @param group 对齐元素分组 (IObjArrayRef<ISqlFormatterAlignmentElem>)
Private Sub doAlignmentElemGroup(ByRef maxAlignmentSize As Integer, ByRef group As IObjArrayRef)
    Dim i As Long
    Dim elem As ISqlFormatterAlignmentElem
    Dim diff As Integer
    Dim tempLen As Integer

    For i = 0 To group.MaxIndex
        Set elem = group.Item(i)
        tempLen = elem.getAlignmentSize(config)

        ' 如果这个分组不需要对齐，则跳过
        If tempLen = -1 Then
            GoTo loopContinue
        End If

        diff = maxAlignmentSize - tempLen
        If diff >= 0 Then
            ' 这里只设置 diff 即可，不需要设置 diff + 1
            elem.setAlignmentSpaceCount diff, config
        End If
loopContinue:
    Next
End Sub

' 校正对齐的长度
'
' @param int size 这里表示的是: 一个分组中的最大长度 + `config.multiNestAlignmentStrSizeDiff`
' @return 校正后的长度
Private Function rectifyAlignmentSize(ByRef size As Integer) As Integer
    ' ==================================================
    ' 1. 快速结束
    ' ==================================================
    ' 1. 如果缓存 `alignmentSizeSet` 的长度为 0，则继续
    If alignmentSizeSet.Count = 0 Then
        ' 2. 退出处理，返回 `-1`
        ' return -1
        rectifyAlignmentSize = -1
        Exit Function
    End If

    ' ==================================================
    ' 2. 声明变量
    ' ==================================================
    ' 1. 最大长度 `int maxSize = size + config.multiNestAlignmentStrSizeDiff`
    Dim maxSize As Integer
    maxSize = size + config.multiNestAlignmentStrSizeDiff
    ' 2. 遍历索引 `long i`
    Dim i As Long
    ' 3. 第 i 个结果 `int cacheVal`
    Dim cacheVal As Integer
    ' 4. 校正结果 `int rectifySize = 9999`
    Dim rectifySize As Integer
    rectifySize = 9999
    ' 5. 标记: 是否进行过校正 `boolean hasRectified = false`
    Dim hasRectified As Boolean

    ' ==================================================
    ' 3. 从缓存 `alignmentSizeSet` 中获取距离 `size` 最近的那个元素
    ' ==================================================
    ' 1. 从 `i = 0` 到 `alignmentSizeSet.Count - 1`，遍历 `alignmentSizeSet`
    For i = 0 To alignmentSizeSet.Count - 1
        ' 2. 获取第 i 个值到 `cacheVal`
        cacheVal = alignmentSizeSet.Item(i)

        ' 3. 检查: 如果 `cacheVal > maxSize`，则跳过
        If cacheVal > maxSize Then
            Goto loopContinue
        End If

        ' 4. 检查: 如果 `cacheVal < size`，则跳过
        If cacheVal < size Then
            Goto loopContinue
        End If

        ' 5. 检查: 如果 `cacheVal < rectifySize`
        If cacheVal < rectifySize Then
            ' 5.1. 设置 `rectifySize = cacheVal`
            rectifySize = cacheVal
            ' 5.2. 设置标记，已经校正过: `hasRectified = true`
            hasRectified = True
        End If
loopContinue:
    Next

    ' ==================================================
    ' 4. 返回结果
    ' ==================================================
    ' 1. 检查: 如果已经校正过，则返回 `rectifySize`: `hasRectified == true`
    If hasRectified = True Then
        ' return rectifySize
        rectifyAlignmentSize = rectifySize
    ' 2. 否则，返回 `-1`
    Else
        ' return -1
        rectifyAlignmentSize = -1
    End If
End Function

' 保存一个校正后的对齐长度
'
' @param size 校正后的对齐长度
Private Sub cacheAlignmentSize(ByVal size As Integer)
    alignmentSizeSet.Add size
End Sub
